home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / lemming / part01 next >
Encoding:
Text File  |  1987-08-05  |  47.9 KB  |  2,226 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i091:  A graphics editor, Part01/04
  5. Message-ID: <777@uunet.UU.NET>
  6. Date: 6 Aug 87 20:25:26 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 2215
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: "Alan W. Paeth" <awpaeth%watcgl.waterloo.edu@RELAY.CS.NET>
  12. Posting-number: Volume 10, Issue 91
  13. Archive-name: lemming/Part01
  14.  
  15. LEMMING is a complete interactive graphics editor which resembles PIC in
  16. providing lines, boxes, circles, and text in various sizes and
  17. emphases (bold, centered, dotted, etc). The implemtation has been proven
  18. on the DEC GPX systems, SUN, and Ikonas Framebuffer. The code is completely
  19. self-contained, and provides an extensive set of internal fonts.
  20.  
  21. Lemming makes no assumptions about the system hardware except that there
  22. is (1) a mouse or tablet with at least one button and (2) there is a bitmap
  23. display (at least one bit deep). The additional code (lemik.c) is a
  24. representative Unix driver for use with an Ikonas framebuffer.
  25.  
  26.  
  27. I am allowing complete public distribution and second party redistribution
  28. of the software on an experimental, non-profit basis.  I maintain a
  29. copyright against unauthorized sale or distribution for commercial or
  30. product applications.
  31.  
  32.     Alan Paeth (awpaeth@watmath)
  33.     c/o Computer Graphics Lab MC6080
  34.     University of Waterloo
  35.     Waterloo, Ontario N2L 3E5
  36.     CANADA
  37.  
  38.  
  39. [  I have not tried this program.  -r$  ]
  40. #!/bin/sh
  41. # This is a shell archive, meaning:
  42. # 1. Remove everything above the #!/bin/sh line.
  43. # 2. Save the resulting text in a file.
  44. # 3. Execute the file with /bin/sh (not csh) to create the files:
  45. #    Makefile
  46. #    .lemrc
  47. #    lem.h
  48. #    lemfont.h
  49. #    lemalloc.c
  50. #    lemalpha.c
  51. #    lemattr.c
  52. #    lembox.c
  53. #    lemcut.c
  54. #    lemedit.c
  55. #    lemelli.c
  56. #    lemfont.c
  57. #    lemgeo.c
  58. #    lemglobal.c
  59. #    lemgroup.c
  60. #    lemhelp.c
  61. #    lemik.c
  62. #    lemio.c
  63. #    lemline.c
  64. if test -f 'Makefile'
  65. then
  66.     echo shar: over-writing existing file "'Makefile'"
  67. fi
  68. cat << \SHAR_EOF > 'Makefile'
  69. CFLAGS = -g
  70.  
  71. OBJ =    lemalloc.o \
  72.     lemalpha.o \
  73.     lemattr.o \
  74.     lembox.o \
  75.     lemcut.o \
  76.     lemedit.o \
  77.     lemelli.o \
  78.     lemfont.o \
  79.     lemgeo.o \
  80.     lemglobal.o \
  81.     lemgroup.o \
  82.     lemhelp.o \
  83.     lemio.o \
  84.     lemline.o \
  85.     lemmain.o \
  86.     lemmark.o \
  87.     lemmisc.o \
  88.     lemobj.o \
  89.     lemobjsup.o \
  90.     lemop.o \
  91.     lempic.o \
  92.     lemrc.o \
  93.     lemselect.o \
  94.     lemspecial.o \
  95.     lemstart.o \
  96.     lemstop.o \
  97.     lemtext.o \
  98.     lemtick.o \
  99.     lemundo.o \
  100.     lemvec.o
  101.  
  102. lemik::    $(OBJ) lemik.o
  103.     cc $(CFLAGS) $(OBJ) lemik.o -lIkonas -lLocator -lm -o /u/awpaeth/bin/lemik
  104.  
  105. lemx::    $(OBJ) lemx.o
  106.     cc $(CFLAGS) $(OBJ) lemx.o -lX -lm -o /u/awpaeth/bin/lemx
  107. SHAR_EOF
  108. chmod +x 'Makefile'
  109. if test -f '.lemrc'
  110. then
  111.     echo shar: over-writing existing file "'.lemrc'"
  112. fi
  113. cat << \SHAR_EOF > '.lemrc'
  114. .lemrc
  115. Lemming .rc for default fonts (up to nine).
  116. Data items are identified by a digit in the left-most column.
  117.  
  118. Note: substitue MR MB & MI for TR TB TI if you (*ugh*) must have ugly fonts.
  119.  
  120.      |-----------------------  Fonts  ------------------------------|
  121. Pnt Line |Display    Typeset            PostScript        |
  122. Sz  Thkn        Rg/Bld/Itl        Rg/Bld/Itl
  123. ------------------------------------------------------------------------
  124. 12   1    TimesRoman    TR TB TI    Times-Bold Times-Bold Times-Bold
  125. 10   2    TimesRoman    TR TB TI    Times-Bold Times-Bold Times-Bold
  126. 18   3    TimesRoman    TR TB TI    Times-Bold Times-Bold Times-Bold
  127. 12   4    Helvetica    SR SB SI    Times-Bold Times-Bold Times-Bold
  128. 10   5    Helvetica    SR SB SI    Times-Bold Times-Bold Times-Bold
  129. 18   6    Helvetica    SR SB SI    Times-Bold Times-Bold Times-Bold
  130. 6    7    Helvetica    SR SB SI    Times-Bold Times-Bold Times-Bold
  131. 10   8    Gacha        CW CW CW    Times-Bold Times-Bold Times-Bold
  132. 12   9    Hippo         GM GM GM    Times-Bold Times-Bold Times-Bold
  133.  
  134. Other popular entries (delete leading space):
  135.  
  136.  18 1    OldEnglish    oe oe oe    Times-Bold Times-Bold Times-Bold
  137. SHAR_EOF
  138. chmod +x '.lemrc'
  139. if test -f 'lem.h'
  140. then
  141.     echo shar: over-writing existing file "'lem.h'"
  142. fi
  143. cat << \SHAR_EOF > 'lem.h'
  144. /*
  145.  * lem.h - lone include file for lem(ming) editor
  146.  *
  147.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  148.  */
  149.  
  150. #include <stdio.h>
  151. #include <strings.h>
  152. #include <ctype.h>
  153.  
  154. #define VERNO 1
  155.  
  156. /*
  157.  * useful arithmetic functions
  158.  */
  159.  
  160. #define MIN(a,b) ((a)<(b)?(a):(b))
  161. #define MAX(a,b) ((a)>(b)?(a):(b))
  162. #define ABS(a) ((a)>0?(a):(-(a)))
  163. #define C(a) ('a'&0x1f)
  164. #define UC(c) (islower((c)) ? toupper((c)) : (c))
  165.  
  166. typedef struct
  167.     {
  168.     char stat;            /* DEL, UNDEL, SEL */
  169.     char group;            /* group id (or zero) */
  170.     char type;            /* LINE, TEXT, ELLI, BOX */
  171.     char align;            /* ALIGNLEFT, ALIGNRGHT, ALIGNCENT */
  172.     char emph;            /* EMPHNONE, EMPHBOLD, EMPHITAL */
  173.     char size;            /* 1..10 */
  174.     short x0, y0, x1, y1;    /* screen coordinates/bounding box */
  175.     char *text;            /* string pointer if text */
  176.     } *pel, el;
  177.  
  178. /*
  179.  * object macros
  180.  */
  181.  
  182. #define forobjects for(i=1; i<lastobj; i++)
  183. #define forobjsrev for(i=lastobj-1; i>0; i--)
  184. #define o objs[i]
  185.  
  186. /*
  187.  * field access
  188.  */
  189.  
  190. #define Ostat (o->stat)
  191. #define Ogroup (o->group)
  192. #define Otype (o->type)
  193. #define Oalign (o->align)
  194. #define Oemph (o->emph)
  195. #define Osize (o->size)
  196. #define Osizer ((Osize >= rclen) ? 1 : Osize)
  197. #define Otext (o->text)
  198. #define Oxs (o->x0)
  199. #define Oys (o->y0)
  200. #define Oxe (o->x1)
  201. #define Oye (o->y1)
  202.  
  203. /*
  204.  * derived field access
  205.  */
  206.  
  207. #define Ox ((o->x0+o->x1+1)/2)
  208. #define Oy ((o->y0+o->y1+1)/2)
  209. #define Ow (o->x1-o->x0)
  210. #define Oh (o->y1-o->y0)
  211. #define Oxl (MIN(o->x0,o->x1))
  212. #define Oyl (MIN(o->y0,o->y1))
  213. #define Oxh (MAX(o->x0,o->x1))
  214. #define Oyh (MAX(o->y0,o->y1))
  215.  
  216. #define Oxlt (Oalign==ALIGNCENT ? Oxs-Oxe/2:(Oalign==ALIGNLEFT ? Oxs:Oxs-Oxe))
  217. #define Oylt (Oys-Oye/2)
  218. /* (Oalign==ALIGNCENT ? Oyl : (Oalign==ALIGNLEFT ? Oy : Oy-Oh)) */
  219. #define Oxht (Oxlt+Oxe)
  220. #define Oyht (Oylt+Oye)
  221. #define Oxcen (Otype==TEXT ? Oxs : Ox)
  222. #define Oycen (Otype==TEXT ? Oys : Oy)
  223.  
  224. #define Osel (o->stat == SEL)
  225. #define Oundel (o->stat == UNDEL)
  226. #define Odel (o->stat == DEL)
  227. #define Onotdel (o->stat != DEL)
  228.  
  229. /*
  230.  * bounds limits
  231.  */
  232.  
  233. #define MAXOBJS 2000
  234. #define MAXCHAR 60
  235.  
  236. /*
  237.  * .lemrc information
  238.  */
  239.  
  240. typedef struct
  241.     {
  242.     int psize;
  243.     int thick;
  244.     char *dsp;
  245.     char *tyr;
  246.     char *tyb;
  247.     char *tyi;
  248.     char *psr;
  249.     char *psb;
  250.     char *psi;
  251.     } *pfontdir, fontdir;
  252.  
  253.  
  254. /*
  255.  * file name (conventions)
  256.  */
  257.   
  258. #define RCNAME  ".lemrc"
  259. #define LEMEXTN "lem"
  260.  
  261. /*
  262.  * initialization defaults (for .rc file in lemrc.c)
  263.  */
  264.  
  265. #define RCLINE 120
  266. #define RCLEN 10
  267. #define RCWIDTH 9
  268.  
  269. #define DEFPSIZEFT 12
  270. #define DEFDENSEFT 1.0
  271. #define DEFIKRFT "TimesRoman"
  272. #define DEFTYRFT "TR"
  273. #define DEFTYBFT "TB"
  274. #define DEFTYIFT "TB"
  275. #define DEFPSRFT "Times-Roman"
  276. #define DEFPSBFT "Times-Bold"
  277. #define DEFPSIFT "Times-Italic"
  278.  
  279. /*
  280.  * system color aliases
  281.  */
  282.  
  283. #define DRAWCOL cwhite
  284. #define SELECTCOL cred
  285. #define ERASECOL cblack
  286. #define MARKONOBJCOL cred
  287. #define MARKONREGCOL cgreen
  288. #define HELPCOL cgreen
  289. #define MARKOFFCOL cblack
  290. #define TICKONCOL cwhite
  291. #define TICKOFFCOL cblack
  292.  
  293. /*
  294.  * event types
  295.  */
  296.  
  297. #define NOEVT 0
  298. #define ALPHA 1
  299. #define CNTRL 2
  300. #define MOUSE 3
  301.  
  302. /*
  303.  * geometric tolerances
  304.  */
  305.  
  306. #define ENDTOL  5    /* near endpoints of lines */
  307. #define MARKTOL 5    /* near a mark */
  308. #define DRAGTOL 5    /* dragging otherwise */
  309. #define FLATTOL 15    /* rectilinear lines */
  310. #define SELTOL  15    /* near selection points */
  311. #define SHRTTOL 5    /* lines may not be (entered) any shorter */
  312. #define LINETOL 5    /* perp distance to a line */
  313. #define TEXTTOL 0    /* text bounding box extra margins (usually no slop) */
  314. #define SPLTTOL 3    /* do not split lines <^K> if made this short */
  315.  
  316. #define TUGPROX 2    /* when towing objects */
  317. #define ARROWLEN 8    /* arrowhead length */
  318. #define MINTICK 8    /* minimum VISIBLE tick spacing */
  319. #define DEFCOPYWID 16    /* default copy width when gridding is off */
  320.  
  321. /*
  322.  * type modes
  323.  */
  324.  
  325. #define LINE 'L'
  326. #define TEXT 'T'
  327. #define ELLI 'E'
  328. #define BOX  'B'
  329.  
  330. /*
  331.  * status modes
  332.  */
  333.  
  334. #define DEL 'D'
  335. #define UNDEL 'U'
  336. #define SEL 'S'
  337.  
  338. /*
  339.  * align modes
  340.  */
  341.  
  342. #define ALIGNLEFT 'L'
  343. #define ALIGNRGHT 'R'
  344. #define ALIGNCENT 'C'
  345.  
  346. /*
  347.  * emphasis modes
  348.  */
  349.  
  350. #define EMPHNONE 'N'
  351. #define EMPHBOLD 'B'
  352. #define EMPHITAL 'I'
  353.  
  354. /*
  355.  * define system font (for help text and unknown fonts)
  356.  */
  357.  
  358. #define SYSFONT 1
  359.  
  360. /*
  361.  * generic object operations
  362.  */
  363.  
  364. #define SELECT 1
  365. #define DESELECT 2
  366. #define DELETE 3
  367. #define UNDELETE 4
  368.  
  369. /*
  370.  * undo flags
  371.  */
  372.  
  373. #define UNDOMOVE 'M'
  374. #define UNDOTUG 'T'
  375. #define UNDOAFF 'A'
  376. #define UNDODEL 'D'
  377. #define UNDONONE 'N'
  378.  
  379. /*
  380.  * application specific
  381.  */
  382.  
  383. #define MARKSIZE 2
  384.  
  385. /*
  386.  * externals (see also lemglobal.c)
  387.  */
  388.  
  389. extern char *firstfile;
  390. extern int displayon;
  391.  
  392. extern int screenw, screenh, cred, cgreen, cblack, cwhite;
  393. extern int changes, tickflag, ticksize, tickdot, tx, ty, txoff, tyoff;
  394. extern int markx, marky, markon, markobj;
  395. extern int anysel;
  396. extern char gtype, galign, gemph, gsize;
  397.  
  398. extern char undo;
  399. extern int unx, uny, unxe, unye;
  400. extern float un11, un12, un21, un22;
  401.  
  402. extern int fontsize[RCLEN];
  403. extern char *picfont[RCLEN], *postfont[RCLEN], *xfont[RCLEN], *ikfont[RCLEN];
  404. extern float rval[RCLEN], gval[RCLEN], bval[RCLEN];
  405.  
  406. extern pel objs[MAXOBJS];
  407. extern int lastobj;
  408.  
  409. extern fontdir lemfont[RCLEN];
  410.  
  411. extern int rclen;
  412.  
  413. extern char line[MAXCHAR], msgtext[MAXCHAR], prompttext[MAXCHAR];
  414.  
  415. /*
  416.  * forward refenreces
  417.  */
  418.  
  419. char *salloc(), *prompt(), getstroke();
  420. SHAR_EOF
  421. if test -f 'lemfont.h'
  422. then
  423.     echo shar: over-writing existing file "'lemfont.h'"
  424. fi
  425. cat << \SHAR_EOF > 'lemfont.h'
  426. /* lemfont.c - routines to create and access binary level strike fonts
  427.  *
  428.  * copywrite (c) 1985, by Alan W. Paeth. All rights reserved
  429.  * 
  430.  * Programmed by Alan Paeth, University of Waterloo, February, 1984
  431.  *
  432.  * NOTE: these fonts began life as 16-bit integers, with opposite byte-
  433.  * order conventions of the VAX. This explains the appearance of short
  434.  * integers, and size counts done in terms of shorts.
  435.  *
  436.  * Also, fonts are represented as a pointer to a contiguous, variable-
  437.  * length structure. Because the actual bitmap is the only data part
  438.  * which varies from font to font, its declaration is ultimate in the
  439.  * structure declaration. FONTHEADERSIZE is the short word offset to it.
  440.  *
  441.  * patched by Alan Paeth, May 1985, to deal with null print strings
  442.  */
  443.  
  444. /* MAX WIDTH */
  445.  
  446. #define LEFT 0
  447. #define RIGHT screenw
  448. #define TOP screenh
  449. #define BOTTOM 0
  450.  
  451. #define MAXWIDTH 1024
  452.  
  453. /* BFont structure - returned by BFontload() */
  454.  
  455. typedef struct BFont_type
  456.     {
  457.     short ascent;
  458.     short descent;
  459.     short mwidth;
  460.     short rasterx;    /* strike scan line length expressed in short ints */
  461.     short widths[257];  /* 257 boundaries between a strike of 256 chars */
  462.     short glyphs[1];    /* var len glyphs starts after FONTHEADSIZE shorts */
  463.     } *BFont;
  464.  
  465. BFont fontload();
  466.  
  467. /* offset to beginning of the glyphs */
  468.  
  469. #define FONTHEADERSIZE 261
  470.  
  471.  
  472. extern BFont bfont[];
  473. SHAR_EOF
  474. if test -f 'lemalloc.c'
  475. then
  476.     echo shar: over-writing existing file "'lemalloc.c'"
  477. fi
  478. cat << \SHAR_EOF > 'lemalloc.c'
  479. /*
  480.  * lemalloc.c -- allocation routines useful to the whole lemming family
  481.  *
  482.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  483.  */
  484.  
  485. #include "lem.h"
  486.  
  487. char *salloc(s)
  488.     char *s;
  489.     {
  490.     char *out;
  491.     out = (char*)(calloc(strlen(s)+1, sizeof(char)));
  492.     strcpy(out, s);
  493.     return(out);
  494.     }
  495.     
  496. objfree(i)
  497.     {
  498.     if (Otext)
  499.     {
  500.     free(Otext);
  501.     Otext = 0;
  502.     }
  503.     free(o);
  504.     o = 0;
  505.     }
  506.  
  507. objalloc(t)
  508.     {
  509.     int i;
  510.     if (lastobj == MAXOBJS)
  511.     {
  512.     forobjects
  513.         {
  514.         if (Odel) break;
  515.         }
  516.     if (i == lastobj) err("out of object space");
  517.     objfree(i);
  518.     }
  519.     else
  520.     {
  521.     i = lastobj++;
  522.     o = (pel)(calloc(1, sizeof(el)));
  523.     }
  524.     Otext = 0;
  525.     Otype = t;
  526.     Otype = t;
  527.     Oalign= galign;
  528.     Oemph = gemph;
  529.     Osize = gsize;
  530.     return(i);
  531.     }
  532.  
  533. objcompress()
  534.     {
  535.     int i, j;
  536.     forobjects
  537.     {
  538.     if (Onotdel) continue;    /* look for a hole */
  539.     for(j=i+1; j<lastobj; j++)
  540.         {
  541.         pel tmp;
  542.         if (objs[j]->stat == DEL) continue;    /* look for non-hole */
  543.         tmp = objs[j];
  544.         objs[j] = objs[i];
  545.         objs[i] = tmp;
  546.         break;
  547.         }
  548.     }
  549.     forobjsrev
  550.     {
  551.     if (Odel) objfree(i);
  552.     else break;
  553.     }
  554.     lastobj = i+1;
  555.     }
  556.  
  557. objnew(i)
  558.     {
  559.     Ostat = DEL;
  560.     Ogroup = 0;
  561.     objectop(i, DEL, UNDEL);
  562.     }
  563. SHAR_EOF
  564. if test -f 'lemalpha.c'
  565. then
  566.     echo shar: over-writing existing file "'lemalpha.c'"
  567. fi
  568. cat << \SHAR_EOF > 'lemalpha.c'
  569. /*
  570.  * lemalpha.c - text control
  571.  *
  572.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  573.  */
  574.  
  575. #include "lem.h"
  576.  
  577. charadd(s, ch)
  578.     char *s, ch;
  579.     {
  580.     int end;
  581.     char str[2];
  582.     str[0] = ch;
  583.     str[1] = '\0';
  584.     charshow(str);
  585.     end = strlen(s);
  586.     if (end < MAXCHAR-1)
  587.     {
  588.     s[end] = ch;
  589.     s[end+1] = '\0';
  590.     }
  591.     }
  592.  
  593. chardel(s,n)
  594.     char *s;
  595.     {
  596.     int end;
  597.     end = strlen(s)-n;
  598.     if (end >= 0)
  599.     {
  600.     charunshow(n);
  601.     s[end] = '\0';
  602.     }
  603.     }
  604.  
  605. chardelall(s)
  606.     char *s;
  607.     {
  608.     if (s) chardel(s, strlen(s));
  609.     }
  610.  
  611. char getstroke()
  612.     {
  613.     int ev, t;
  614.     char ch;
  615. /*
  616.  * get next alpha keystroke (null on other event)
  617.  */
  618.     do  {
  619.     ev = getevent(&t, &t, &t, &t, &ch);
  620.     } while ((ev == NOEVT) || ((ev == CNTRL) && (ch == '\0')));
  621.     if ((ev == ALPHA) || (ev == CNTRL)) return(ch);
  622.     return('\0');
  623.     }
  624.  
  625. char *prompt(pstr)
  626.     char *pstr;
  627.     {
  628.     char ch, pout[MAXCHAR], *rstr;
  629.     pout[0] = '\0';
  630.     strncpy(prompttext, pstr, MAXCHAR);
  631.     msgclear();
  632.     chardelall(line);
  633.     charshow(prompttext);
  634.     ch = '\0';
  635.     while((ch != C(M)) && (ch != C(J)))
  636.     {
  637.     ch = getstroke();
  638.     if (ch >= ' ') charadd(pout, ch);
  639.     else if (ch == '\b') chardel(pout,1);
  640.     }
  641.     rstr = salloc(pout);
  642.     chardelall(pout);
  643.     chardelall(prompttext);
  644.     return(rstr);
  645.     }
  646.  
  647. msgpost(s)
  648.     char *s;
  649.     {
  650.     msgclear();
  651.     strncpy(msgtext, s, MAXCHAR);
  652.     charshow(msgtext);
  653.     }
  654.  
  655. msgclear()
  656.     {
  657.     chardelall(msgtext);
  658.     }
  659.  
  660. stringadd()
  661.     {
  662.     textadd(markx, marky, line);
  663.     if (line && strlen(line))
  664.     {
  665.     int hgt;
  666.     hgt = fontleading(gsize);
  667.     markupdate(markx, MAX(marky-hgt, hgt));
  668.     }
  669.     chardelall(line);
  670.     }
  671.     
  672. fontheight(f)
  673.     {
  674.     return(lemfont[(f >= rclen) ? 1 : f].psize);
  675.     }
  676.  
  677. fontleading(f)
  678.     {
  679.     return((fontheight(f)*6+2)/5);
  680.     }
  681. SHAR_EOF
  682. if test -f 'lemattr.c'
  683. then
  684.     echo shar: over-writing existing file "'lemattr.c'"
  685. fi
  686. cat << \SHAR_EOF > 'lemattr.c'
  687. /*
  688.  * lemattr.c - change object attributes (and reset global defaults)
  689.  *
  690.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  691.  */
  692.  
  693. #include "lem.h"
  694.  
  695. remake(newtype)
  696.     {
  697.     int i;
  698.     gtype = newtype;
  699.     forobjects
  700.     {
  701.     if (Osel && (Otype != newtype) && (Otype != TEXT))
  702.         {
  703.         objectop(i, SEL, DEL);
  704.         Otype = newtype;
  705.         objectop(i, DEL, SEL);
  706.         }
  707.     }
  708.     }
  709.  
  710. setattr(ch)
  711.     char ch;
  712.     {
  713.     switch(UC(ch))
  714.     {
  715.     case 'B': gemph = EMPHBOLD; break;
  716.     case 'I': gemph = EMPHITAL; break;
  717.     case 'N': gemph = EMPHNONE; break;
  718.     case 'L': galign = ALIGNLEFT; break;
  719.     case 'R': galign = ALIGNRGHT; break;
  720.     case 'C': galign = ALIGNCENT; break;
  721.     case '0': gsize = 1; galign = ALIGNCENT; gemph = EMPHNONE; break;
  722.     case '1':
  723.     case '2':
  724.     case '3':
  725.     case '4':
  726.     case '5':
  727.     case '6':
  728.     case '7':
  729.     case '8':
  730.     case '9': gsize = ch-'0'; break;
  731.     default: return(0);        /* invalid char - fail */
  732.     }
  733.     return(1);    /* good char */
  734.     }
  735. /*
  736.  * rewrite all objects with these attributes
  737.  */
  738.  
  739. forceattr()
  740.     {
  741.     int i, salign, semph, ssize;
  742.     char ch;
  743.     ch = getstroke();
  744.     if (setattr(ch))        /* set global attributes */
  745.     {
  746.     salign = galign;    /* save new global attributes */
  747.     semph = gemph;
  748.     ssize = gsize;
  749.     forobjects
  750.         {
  751.         if (Osel)
  752.         {
  753.         objectop(i, SEL, DEL);    /* get object */
  754.         galign = Oalign;    /* set matching global attribs, */
  755.         gemph = Oemph;
  756.         gsize = Osize;
  757.         setattr(ch);        /* reset some new attribute(s) */
  758.         Oalign = galign;    /* write back */
  759.         Oemph = gemph;
  760.         Osize = gsize;
  761.         objresize(i);        /* in case this changes geometry */
  762.         objectop(i, DEL, SEL);
  763.         }
  764.         }
  765.     galign = salign;    /* reset to new global attributes */
  766.     gemph = semph;
  767.     gsize = ssize;
  768.     }
  769.     }
  770. SHAR_EOF
  771. if test -f 'lembox.c'
  772. then
  773.     echo shar: over-writing existing file "'lembox.c'"
  774. fi
  775. cat << \SHAR_EOF > 'lembox.c'
  776. /*
  777.  * lembox.c - box primitives
  778.  *
  779.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  780.  */
  781.  
  782. #include "lem.h"
  783.  
  784. boxresize(i)
  785.     {
  786.     }
  787.  
  788. boxnearpt(i, x, y)
  789.     {
  790.     int dx, dy;
  791.     if (ptinrect(x, y, Oxl, Oyl, Oxh, Oyh, LINETOL))
  792.         {
  793.     dx = MIN(ABS(Ox-x), ABS(Oxh-x));    /* simplified for Iris C */
  794.     dx = MIN(ABS(Oxl-x), dx);
  795.     dy = MIN(ABS(Oy-y), ABS(Oyh-y));
  796.     dy = MIN(ABS(Oyl-y), dy);
  797.         if ((dx < ENDTOL) && (dy < 2*ENDTOL)) return(1);
  798.         if ((dx < 2*ENDTOL) && (dy < ENDTOL)) return(1);
  799.     }
  800.     return(0);
  801.     }
  802.  
  803. boxinrect(i, xl, yl, xh, yh)
  804.     {
  805.     return(objsupinrect(i, xl, yl, xh, yh));
  806.     }
  807.  
  808. boxcantug(i, x, y)
  809.     {
  810.     return(objsupcantug(i, x, y));
  811.     }
  812.  
  813. boxtug(i, xs, ys, xe, ye)
  814.     {
  815.     int lx, mx, hx, ly, my, hy;
  816.     lx = ABS(Oxl-xs);
  817.     mx = ABS(Ox-xs);
  818.     hx = ABS(Oxh-xs);
  819.     if (lx<mx && lx<hx) { if (Oxs<Oxe) Oxs = xe; else Oxe = xe; }
  820.     if (hx<lx && hx<mx) { if (Oxs>Oxe) Oxs = xe; else Oxe = xe; }
  821.     ly = ABS(Oyl-ys);
  822.     my = ABS(Oy-ys);
  823.     hy = ABS(Oyh-ys);
  824.     if (ly<my && ly<hy) { if (Oys<Oye) Oys = ye; else Oye = ye; }
  825.     if (hy<ly && hy<my) { if (Oys>Oye) Oys = ye; else Oye = ye; }
  826.     if (mx<=hx && mx<=lx && my<=hy && my<=ly) boxmove(i, xe-xs, ye-ys);
  827.     }
  828.  
  829. boxalign(i, x, y)
  830.     int *x, *y;
  831.     {
  832.     int l, m, h;
  833.     l = ABS(Oxl-*x);
  834.     m = ABS(Ox-*x);
  835.     h = ABS(Oxh-*x);
  836.     if (l<m && l<h) *x = Oxl;
  837.     if (m<h && m<l) *x = Ox;
  838.     if (h<=l && h<=m) *x = Oxh;
  839.     l = ABS(Oyl-*y);
  840.     m = ABS(Oy-*y);
  841.     h = ABS(Oyh-*y);
  842.     if (l<m && l<h) *y = Oyl;
  843.     if (m<h && m<l) *y = Oy;
  844.     if (h<=l && h<=m) *y = Oyh;
  845.     }
  846.  
  847. boxmove(i, x, y)
  848.     {
  849.     objsupmove(i, x, y);
  850.     }
  851.  
  852. boxaffine(i, m11, m12, m21, m22)
  853.     float m11, m12, m21, m22;
  854.     {
  855.     objsupaffine(i, m11, m12, m21, m22, 1);
  856.     }
  857.  
  858. boxdraw(i, col)
  859.     {
  860.     int wid;
  861.     wid = lemfont[Osizer].thick;
  862.     drawvec(Oxs, Oys, Oxe, Oys, col, wid, Oemph);
  863.     drawvec(Oxe, Oys, Oxe, Oye, col, wid, Oemph);
  864.     drawvec(Oxe, Oye, Oxs, Oye, col, wid, Oemph);
  865.     drawvec(Oxs, Oye, Oxs, Oys, col, wid, Oemph);
  866.     }
  867. SHAR_EOF
  868. if test -f 'lemcut.c'
  869. then
  870.     echo shar: over-writing existing file "'lemcut.c'"
  871. fi
  872. cat << \SHAR_EOF > 'lemcut.c'
  873. /*
  874.  * lemcut.c - code for chopping against intersecting lines.
  875.  *
  876.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  877.  */
  878.  
  879. #include "lem.h"
  880.  
  881. cutlines()
  882.     {
  883.     int i, x0, x1, y0, y1, x2, y2, x3, y3;
  884.     forobjects
  885.     {
  886.     if (Osel && Otype == LINE)
  887.         {
  888.         x2 = Oxs;
  889.         y2 = Oys;
  890.         x3 = Oxe;
  891.         y3 = Oye;
  892.         {
  893.         int i, j, xs, ys;        /* new "i" variable */
  894.         long det, det2, a, b;
  895.         forobjects
  896.             {
  897.             if (Otype != LINE) continue;
  898.             if (Ostat != UNDEL) continue; /* don't cut sel lines */ 
  899.             x0 = Oxs;
  900.             y0 = Oys;
  901.             x1 = Oxe;
  902.             y1 = Oye;
  903.             if ((x0 == x2) && (y0 == y2)) continue; /* share endpnts */
  904.             if ((x1 == x2) && (y1 == y2)) continue;
  905.             if ((x0 == x3) && (y0 == y3)) continue;
  906.             if ((x1 == x3) && (y1 == y3)) continue;
  907.             det = (x1-x0)*(y3-y2) - (y1-y0)*(x3-x2);
  908.             if (det == 0) continue;
  909.             det2 = det/2;
  910.             a = ((y3-y2)*(x2-x0) + (x2-x3)*(y2-y0));
  911.             b = ((y1-y0)*(x2-x0) + (x0-x1)*(y2-y0));
  912.             if (a == 0) continue;
  913.             if ((a < 0) && (a <= det)) continue;
  914.             if ((a > 0) && (a >= det)) continue;
  915.             if ((b < 0) && (b <= det)) continue;
  916.             if ((b > 0) && (b >= det)) continue;
  917.             xs = x0 + (a*(x1-x0)+det2)/det;
  918.             ys = y0 + (a*(y1-y0)+det2)/det;
  919.             if (dist(x0, y0, xs, ys) <= SPLTTOL) continue;
  920.             if (dist(x1, y1, xs, ys) <= SPLTTOL) continue;
  921.             objectop(i, UNDEL, DEL);
  922.             j = objalloc(LINE);
  923.             copyattr(j, i);
  924.             lineupdate(i, x0, y0, xs, ys);
  925.             lineupdate(j, xs, ys, x1, y1);
  926.             objectop(i, DEL, UNDEL);
  927.             objectop(j, DEL, UNDEL);
  928.             }
  929.         }
  930.         }
  931.     }
  932.     }
  933. SHAR_EOF
  934. if test -f 'lemedit.c'
  935. then
  936.     echo shar: over-writing existing file "'lemedit.c'"
  937. fi
  938. cat << \SHAR_EOF > 'lemedit.c'
  939. /*
  940.  * lemedit.c - object manipulation
  941.  *
  942.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  943.  */
  944.  
  945. #include "lem.h"
  946.  
  947. moveselect(x, y)
  948.     {
  949.     int i;
  950. /*
  951.  * set flag and record last movement for undo
  952.  */
  953.     unx = x;
  954.     uny = y;
  955.     undo = UNDOMOVE;
  956. /*
  957.  * do the move
  958.  */
  959.     if (!anysel) return;
  960.     forobjects
  961.     {
  962.     if (Osel)
  963.         {
  964.         objectop(i, SEL, DEL);
  965.         objmove(i, x, y);
  966.         objectop(i, DEL, SEL);
  967.         }
  968.     }
  969.     }
  970.  
  971. tugunselect(xs, ys, xe, ye)
  972.     {
  973.     int i;
  974. /*
  975.  * set flag and record last movement for undo
  976.  */
  977.     unx =  xs;
  978.     uny =  ys;
  979.     unxe = xe;
  980.     unye = ye;
  981.     undo = UNDOTUG;
  982. /*
  983.  * do the tug
  984.  */
  985.     if (anysel) return;
  986.     forobjects
  987.     {
  988.     if (Oundel && objcantug(i, xs, ys))
  989.         {
  990.         objectop(i, UNDEL, DEL);
  991.         objtug(i, xs, ys, xe, ye);
  992.         objectop(i, DEL, UNDEL);
  993.         }
  994.     }
  995.     }
  996.  
  997. copyattr(j, i)
  998.     {
  999.     objs[j]->stat = Ostat;
  1000.     objs[j]->type = Otype;
  1001.     objs[j]->x0 = Oxs;
  1002.     objs[j]->y0 = Oys;
  1003.     objs[j]->x1 = Oxe;
  1004.     objs[j]->y1 = Oye;
  1005.     objs[j]->align = Oalign;
  1006.     objs[j]->emph = Oemph;
  1007.     objs[j]->size = Osize;
  1008.     objs[j]->group = Ogroup;
  1009.     if (Otext) objs[j]->text = salloc(Otext);
  1010.     }
  1011.  
  1012. copysel()
  1013.     {
  1014.     int i, j, g, dx, dy;
  1015.     if (!anysel) return;
  1016.     dx = tickflag ? tx : DEFCOPYWID;
  1017.     dy = tickflag ? ty : DEFCOPYWID;
  1018.     g = uniquegroup();
  1019.     forobjects
  1020.     {
  1021.     if (Osel)
  1022.         {
  1023.         j = objalloc(Otype);
  1024.         copyattr(j, i);
  1025.         objs[j]->x0 = Oxs+dx;
  1026.         objs[j]->y0 = Oys+dy;
  1027.         if (Otype != TEXT)
  1028.             {
  1029.         objs[j]->x1 = Oxe+dx;
  1030.             objs[j]->y1 = Oye+dy;
  1031.         }
  1032.         objs[j]->group = g;
  1033.         objs[j]->stat = DEL;
  1034.         objectop(i, SEL, UNDEL);
  1035.         objectop(j, DEL, UNDEL);
  1036.         }
  1037.     }
  1038.     if (markobj) markupdate(markx+dx, marky+dy);
  1039.     }
  1040. SHAR_EOF
  1041. if test -f 'lemelli.c'
  1042. then
  1043.     echo shar: over-writing existing file "'lemelli.c'"
  1044. fi
  1045. cat << \SHAR_EOF > 'lemelli.c'
  1046. /*
  1047.  * lemselect.c - object selection and proximity testing
  1048.  *
  1049.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1050.  */
  1051.  
  1052. #include "lem.h"
  1053.  
  1054. elliresize(i)
  1055.     {
  1056.     }
  1057.  
  1058. ellinearpt(i, x, y)
  1059.     {
  1060.     if (ptinrect(x, y, Oxl, Oyl, Oxh, Oyh, LINETOL))
  1061.     {
  1062.         if (dist(Ox,  Oyh, x, y) < ENDTOL) return(1);
  1063.         if (dist(Ox,  Oyl, x, y) < ENDTOL) return(1);
  1064.         if (dist(Oxl, Oy,  x, y) < ENDTOL) return(1);
  1065.         if (dist(Oxh, Oy,  x, y) < ENDTOL) return(1);
  1066.         if (dist(Ox,  Oy,  x, y) < ENDTOL) return(1);
  1067.     }
  1068.     return(0);
  1069.     }
  1070.  
  1071. elliinrect(i, xl, yl, xh, yh)
  1072.     {
  1073.     return(objsupinrect(i, xl, yl, xh, yh));
  1074.     }
  1075.  
  1076. ellicantug(i, x, y)
  1077.     {
  1078.     return(objsupcantug(i, x, y));
  1079.     }
  1080.  
  1081. ellitug(i, xs, ys, xe, ye)
  1082.     {
  1083.     int n, s, e, w, c;
  1084.     n = dist(Ox,  Oyh, xs, ys);
  1085.     s = dist(Ox,  Oyl, xs, ys);
  1086.     w = dist(Oxl, Oy,  xs, ys);
  1087.     e = dist(Oxh, Oy,  xs, ys);
  1088.     c = dist(Ox,  Oy,  xs, ys);
  1089.     if (n<s && n<e && n<w && n<c) { if (Oys>Oye) Oys = ye; else Oye = ye; }
  1090.     if (s<n && s<e && s<w && s<c) { if (Oys<Oye) Oys = ye; else Oye = ye; }
  1091.     if (e<w && e<n && e<s && e<c) { if (Oxs>Oxe) Oxs = xe; else Oxe = xe; }
  1092.     if (w<e && w<n && w<s && w<c) { if (Oxs<Oxe) Oxs = xe; else Oxe = xe; }
  1093.     if (c<=n && c<=s && c<=e && c<=w) ellimove(i, xe-xs, ye-ys);
  1094.     }
  1095.  
  1096. ellialign(i, x, y)
  1097.     int *x, *y;
  1098.     {
  1099.     int n, s, e, w, c;
  1100.     n = dist(Ox,  Oyh, *x, *y);
  1101.     s = dist(Ox,  Oyl, *x, *y);
  1102.     w = dist(Oxl, Oy,  *x, *y);
  1103.     e = dist(Oxh, Oy,  *x, *y);
  1104.     c = dist(Ox,  Oy,  *x, *y);
  1105.     *x = Ox;
  1106.     *y = Oy;
  1107.     if (n<s && n<e && n<w && n<c) *y = Oyh;
  1108.     if (s<n && s<e && s<w && s<c) *y = Oyl;
  1109.     if (e<w && e<n && e<s && e<c) *x = Oxh;
  1110.     if (w<=e && w<=n && w<=s && w<=c) *x = Oxl;
  1111.     }
  1112.  
  1113. ellimove(i, x, y)
  1114.     {
  1115.     objsupmove(i, x, y);
  1116.     }
  1117.  
  1118. elliaffine(i, m11, m12, m21, m22)
  1119.     float m11, m12, m21, m22;
  1120.     {
  1121.     objsupaffine(i, m11, m12, m21, m22, 1);
  1122.     }
  1123.  
  1124. ellidraw(i, col)
  1125.     {
  1126.     int wid, hw2, hh2, hw7, hh7;
  1127.     wid = lemfont[Osizer].thick;
  1128.     hw2 = ABS(Ow)/4;
  1129.     hh2 = ABS(Oh)/4;
  1130.     hw7 = ABS(Ow)*7/16;
  1131.     hh7 = ABS(Oh)*7/16;
  1132.     drawvec(Oxl,    Oy,     Ox-hw7, Oy+hh2, col, wid, Oemph);
  1133.     drawvec(Ox-hw7, Oy+hh2, Ox-hw2, Oy+hh7, col, wid, Oemph);
  1134.     drawvec(Ox-hw2, Oy+hh7, Ox,     Oyh,    col, wid, Oemph);
  1135.     drawvec(Ox,     Oyh,    Ox+hw2, Oy+hh7, col, wid, Oemph);
  1136.     drawvec(Ox+hw2, Oy+hh7, Ox+hw7, Oy+hh2, col, wid, Oemph);
  1137.     drawvec(Ox+hw7, Oy+hh2, Oxh,    Oy,     col, wid, Oemph);
  1138.     drawvec(Oxh,    Oy,     Ox+hw7, Oy-hh2, col, wid, Oemph);
  1139.     drawvec(Ox+hw7, Oy-hh2, Ox+hw2, Oy-hh7, col, wid, Oemph);
  1140.     drawvec(Ox+hw2, Oy-hh7, Ox,     Oyl,    col, wid, Oemph);
  1141.     drawvec(Ox,     Oyl,    Ox-hw2, Oy-hh7, col, wid, Oemph);
  1142.     drawvec(Ox-hw2, Oy-hh7, Ox-hw7, Oy-hh2, col, wid, Oemph);
  1143.     drawvec(Ox-hw7, Oy-hh2, Oxl,    Oy,     col, wid, Oemph);
  1144.     }
  1145. SHAR_EOF
  1146. if test -f 'lemfont.c'
  1147. then
  1148.     echo shar: over-writing existing file "'lemfont.c'"
  1149. fi
  1150. cat << \SHAR_EOF > 'lemfont.c'
  1151. /*
  1152.  * lemfont.c - routines to create and access binary level strike fonts
  1153.  *
  1154.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1155.  *
  1156.  * Programmed by Alan Paeth, University of Waterloo, February, 1984
  1157.  *
  1158.  * NOTE: these fonts began life as 16-bit integers, with opposite byte-
  1159.  * order conventions of the VAX. This explains the appearance of short
  1160.  * integers, and size counts done in terms of shorts.
  1161.  *
  1162.  * Also, fonts are represented as a pointer to a contiguous, variable-
  1163.  * length structure. Because the actual bitmap is the only data part
  1164.  * which varies from font to font, its declaration is ultimate in the
  1165.  * structure declaration. FONTHEADERSIZE is the short word offset to it.
  1166.  *
  1167.  * patched by Alan Paeth, May 1985, to deal with null print strings
  1168.  */
  1169.  
  1170. #include "lem.h"
  1171. #include "lemfont.h"
  1172.  
  1173. /* system constants */
  1174.  
  1175. #define NULL 0
  1176. #define READMODE 0
  1177. #define OPENFAIL -1
  1178.  
  1179. /* bit masking constants useful with non sign-extended shifts */
  1180.  
  1181. #define MAXPOS 0x77777777
  1182. #define MAXNEG 0x80000000
  1183.  
  1184. /* private tables to speed up bit test operations */
  1185.  
  1186. short intab[17] =
  1187.     { 0x0000,
  1188.       0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
  1189.       0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
  1190.  
  1191. int outtab[33] =
  1192.     { 0x00000000,
  1193.       0x00000001, 0x00000002, 0x00000004, 0x00000008,
  1194.       0x00000010, 0x00000020, 0x00000040, 0x00000080,
  1195.       0x00000100, 0x00000200, 0x00000400, 0x00000800,
  1196.       0x00001000, 0x00002000, 0x00004000, 0x00008000,
  1197.       0x00010000, 0x00020000, 0x00040000, 0x00080000,
  1198.       0x00100000, 0x00200000, 0x00400000, 0x00800000,
  1199.       0x01000000, 0x02000000, 0x04000000, 0x08000000,
  1200.       0x10000000, 0x20000000, 0x40000000, 0x80000000 };
  1201.  
  1202.  
  1203. /* PUBLIC PROCEDURES */
  1204.  
  1205. BFont fontload(filename)
  1206. char *filename;
  1207.     {
  1208.     BFont curfont;
  1209.     short xxx, minascii, maxascii, ascent;
  1210.     short mwidth, descent, rasterx, height;
  1211.     int i;
  1212.     long fd, readlen;
  1213.  
  1214.     if ((fd = open(filename, READMODE)) == OPENFAIL) return (NULL);
  1215.  
  1216.     sread(fd, &xxx, 2);        /* first word is a throwaway */
  1217.     sread(fd, &minascii, 2);
  1218.     sread(fd, &maxascii, 2);
  1219.     sread(fd, &mwidth, 2);
  1220.     sread(fd, &xxx, 2);        /* length is a throwaway */
  1221.     sread(fd, &ascent, 2);
  1222.     sread(fd, &descent, 2);
  1223.     sread(fd, &xxx, 2);        /* xoffset unused unless kerned fonts */
  1224.     sread(fd, &rasterx, 2);
  1225.  
  1226.     height = ascent + descent;
  1227.  
  1228.     curfont = (BFont)(calloc( rasterx*height + FONTHEADERSIZE , 2));
  1229.     if (curfont == NULL)
  1230.     {
  1231.     close(fd);
  1232.     return (NULL);
  1233.     }
  1234.  
  1235.     curfont->ascent = ascent;
  1236.     curfont->descent = descent;
  1237.     curfont->mwidth = mwidth;
  1238.     curfont->rasterx = rasterx;
  1239.  
  1240.     readlen = rasterx * height * 2;    /* convert shorts to bytes */
  1241.     if (sread(fd, &(curfont->glyphs[0]), readlen) != readlen)
  1242.     {
  1243.     close(fd);
  1244.     free(curfont);
  1245.     return (NULL);
  1246.     }
  1247.  
  1248.     for (i=0; i<256; i++) curfont->widths[i] = 0;
  1249.  
  1250.     readlen = (maxascii - minascii + 2) * 2;    /* n+1 widths (short ints) */
  1251.     if (sread(fd, &(curfont->widths[minascii]), readlen ) != readlen)
  1252.     {
  1253.     close(fd);
  1254.     free(curfont);
  1255.     return (NULL);
  1256.     }
  1257.     close(fd);
  1258.     return (curfont);
  1259.     }
  1260.  
  1261. fontfree(arg)
  1262.     BFont arg;
  1263.     {
  1264.     free(arg);
  1265.     }
  1266.  
  1267. fontmeasure(font, string, emph)
  1268. BFont font;
  1269. char *string;
  1270.     {
  1271.     int ch;
  1272.     int len = 0;
  1273.     if (font == NULL) err("font == NULL\n");
  1274.     while (ch = *(string++)) len += (font->widths[ch+1] - font->widths[ch]);
  1275.     if (len == 0) return(0);        /* no emphasis fudge if no string */
  1276.     if (emph == EMPHITAL) len += font->ascent / 4;
  1277.     if (emph == EMPHBOLD) ++len;
  1278.     return(len);
  1279.     }
  1280.  
  1281. fontwrite(font, x, y, string, emph, fontcol)
  1282.     {
  1283.     privfontwrite(bfont[font], x, y, string, emph, fontcol);
  1284.     }
  1285.  
  1286. privfontwrite(font, x, y, string, emph, fontcol)
  1287. BFont font;
  1288. int x, y;
  1289. char *string;
  1290.     {
  1291.     static long bitbuf[MAXWIDTH/32];
  1292.  
  1293.     int smeasure, bufsize, bufsizew, rows, inlen;
  1294.     char ch, *strcopy;
  1295.     short *inbase, *inaddr, *widthptr, inoffset;
  1296.     int i, curpos, skew, inmaski, outmaski;
  1297.     long *outaddr;
  1298.  
  1299.     y = screenh - y;
  1300.     smeasure = fontmeasure(font, string, emph);
  1301.     if (smeasure == 0) return;        /* QUICK RETURN: no string */
  1302.     bufsize = MIN(x + smeasure, RIGHT) - MAX(x, LEFT);
  1303.  
  1304. /* clip to physical resources */
  1305.  
  1306.     bufsize = MIN(bufsize, MAXWIDTH);
  1307.  
  1308.     bufsizew = (bufsize-1) / 32 + 1;    /* words to hold bits, rounded up */
  1309.     inbase = &(font->glyphs[0]);
  1310.     rows = font->ascent+font->descent;    /* +1 for predecrementing */
  1311. /* y adjust */
  1312. /*  y -= 0;                    /* upper lh-corner */
  1313. /*  y -= font->ascent;                /* lh baseline */
  1314. /**/y -= (font->ascent+font->descent)/2;    /* lh center line */
  1315.  
  1316.     ++rows;
  1317.     while (--rows)            /* +1 for predecrementing speed */
  1318.     {
  1319.     if (bufsize > 0 && y >= BOTTOM && y < TOP)
  1320.         {
  1321.         if (emph == EMPHITAL)
  1322.         skew = rows / 4;
  1323.         else skew = 0;
  1324.         curpos= MIN(x+skew-LEFT,0);    /* bitpos in output buffer */
  1325.         i = bufsizew;
  1326.         while (i) bitbuf[--i] = 0;    /* clear ALL output buffer */
  1327.  
  1328.         strcopy = string;        /* set up for output */
  1329.         outmaski = 32;
  1330.         outaddr = bitbuf;
  1331.  
  1332.         while (ch = *(strcopy++))    /* character loop */
  1333.         {
  1334.         widthptr = &(font->widths[ch]);
  1335.         inoffset = *widthptr;
  1336.  
  1337. /* inlen is min of (room left in buffer), (char width) */
  1338.  
  1339.         inlen = min(bufsize-skew-curpos, (*(++widthptr) - inoffset) );
  1340.  
  1341.         inaddr = inbase + inoffset/16;
  1342.         inmaski = 16 - (inoffset & 15);    /* 15+1 for predecrementing */
  1343.         ++inlen;            /*   +1 for predecrementing */
  1344.         while (--inlen)            /* draw while char/room left */
  1345.             {
  1346.             if (++curpos > 0)        /* position at end of draw */
  1347.             {
  1348.             if (*inaddr&intab[inmaski]) *outaddr|=outtab[outmaski];
  1349.             if (!(--outmaski)) { outmaski = 32; ++outaddr; }
  1350.             }
  1351.             if (!(--inmaski)) {  inmaski = 16; ++inaddr ; }
  1352.             }
  1353.         }
  1354.         if (emph == EMPHBOLD)
  1355.         {
  1356.         for(i = bufsizew - 1; i > 0; --i)
  1357.             {
  1358.             bitbuf[i] |= (bitbuf[i])>>1;
  1359.             if (bitbuf[i-1]&1) bitbuf[i] |= MAXNEG;
  1360.             }
  1361.         bitbuf[i] |= (bitbuf[i])>>1;
  1362.         }
  1363. /*
  1364.         if ((emph == EMPHUNDERSCORE) && (rows == font->descent))
  1365.         {
  1366.         i = bufsizew;
  1367.         while (i) bitbuf[--i] = -1;
  1368.         }
  1369. */
  1370.         writescan( MAX(x+skew, LEFT), y, bufsize-skew, bitbuf, fontcol);
  1371.         }
  1372.     ++y;
  1373.     inbase += font->rasterx;
  1374.     }
  1375.     }
  1376.  
  1377. /* PRIVATE PROCEDURES */
  1378.  
  1379. static min(a,b)
  1380.     long a,b;
  1381.     {
  1382.     return( (a < b) ? a : b );
  1383.     }
  1384.  
  1385. /*
  1386.  * sread is analogous to unix read, but will swap bytes on machines with
  1387.  * byte order opposite that of the VAX. This makes the font files portable.
  1388.  */
  1389.  
  1390. sread(d, buf, nbytes)
  1391.     register char *buf;
  1392.     register int nbytes;
  1393.     {
  1394.     register char *test, l, r;
  1395.     short order = 1;
  1396.     int ret;
  1397.     test = (char*)(&order);
  1398.     ret = read(d, buf, nbytes);
  1399.     if (*test != '\001')
  1400.     {
  1401.     while( nbytes > 1)    /* non-vax: do byte swap */
  1402.         {
  1403.         l = *buf++;
  1404.         r = *buf;
  1405.         *buf = l;
  1406.         *--buf = r;
  1407.         buf += 2;
  1408.         nbytes -= 2;
  1409.         }
  1410.     }
  1411.     return(ret);
  1412.     }
  1413. SHAR_EOF
  1414. chmod +x 'lemfont.c'
  1415. if test -f 'lemgeo.c'
  1416. then
  1417.     echo shar: over-writing existing file "'lemgeo.c'"
  1418. fi
  1419. cat << \SHAR_EOF > 'lemgeo.c'
  1420. /*
  1421.  * lemgeo.c - low-level geometric routines
  1422.  *
  1423.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1424.  */
  1425.  
  1426. #include "lem.h"
  1427.  
  1428. ptinrect(px, py, xl, yl, xh, yh, tol)
  1429.     {
  1430.     xl -= tol;
  1431.     yl -= tol;
  1432.     xh += tol;
  1433.     yh += tol;
  1434.     return((xl<=px) && (xh>=px) && (yl<=py) && (yh>=py));
  1435.     }
  1436.  
  1437. hypot(x, y)
  1438.     {
  1439.     x = ABS(x);
  1440.     y = ABS(y);
  1441.     if (x>y) return(x+y/2);
  1442.     return(y+x/2);
  1443.     }
  1444.  
  1445. dist(x0, y0, x1, y1)
  1446.     {
  1447.     return(hypot(x1-x0, y1-y0));
  1448.     }
  1449.  
  1450. spacealign(x, y)
  1451.     int *x, *y;
  1452.     {
  1453.     int dx, dy;
  1454.     dx = ABS(*x-markx);
  1455.     dy = ABS(*y-marky);
  1456.     if (dx > FLATTOL * dy) *y = marky;
  1457.     if (dy > FLATTOL * dx) *x = markx;
  1458.     tickalign(x, y);
  1459.     }
  1460. SHAR_EOF
  1461. if test -f 'lemglobal.c'
  1462. then
  1463.     echo shar: over-writing existing file "'lemglobal.c'"
  1464. fi
  1465. cat << \SHAR_EOF > 'lemglobal.c'
  1466. /*
  1467.  * lemglobal.c -- global variables
  1468.  *
  1469.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1470.  */
  1471.  
  1472. #include "lem.h"
  1473. #include "lemfont.h"
  1474.  
  1475. /* global object array */
  1476.  
  1477. pel objs[MAXOBJS];
  1478. int lastobj;
  1479.  
  1480. /* global font information */
  1481.  
  1482. fontdir lemfont[RCLEN];
  1483. BFont bfont[RCLEN];
  1484.  
  1485. int rclen;
  1486.  
  1487. /* command line globals */
  1488.  
  1489. char *firstfile;    /* name of first input dataset */
  1490. int displayon;        /* true if display is running */
  1491.  
  1492. /* global cursor and screen info */
  1493.  
  1494. int changes;        /* objects added/deleted since last write */
  1495. int tickflag, ticksize;    /* true if ticks turned on, tick size [0..6] */
  1496. int tx, ty;        /* tick x,y spacing */
  1497. int txoff, tyoff;    /* tick x,y offset */
  1498. int tickdot;        /* hwidth of tick dot: 0/1 for DEC/SUN X-windows */
  1499. int markx, marky;    /* current mark */
  1500. int markon;        /* if any mark is present */
  1501. int markobj;        /* object number if mark is present and on an object */
  1502. int anysel;        /* if at least one selection */
  1503.  
  1504. char gtype;        /* default object creation */
  1505. char galign;        /* default alignment */
  1506. char gemph;        /* default emphasis */
  1507. char gsize;        /* default size */
  1508.  
  1509. /* undo information */
  1510.  
  1511. char undo;        /* 'T' - transform 'M' - move 'U' - undelete */ 
  1512. int unx,uny, unxe,unye; /* translation and affine transformation values */
  1513. float un11, un12, un21, un22;
  1514.  
  1515. int screenw, screenh;            /* maximum screen size */
  1516. int cred, cgreen, cwhite, cblack;    /* system colors */
  1517. char line[MAXCHAR];            /* input text line */
  1518. char msgtext[MAXCHAR];            /* pending warning messages */
  1519. char prompttext[MAXCHAR];        /* messages to the user */
  1520. SHAR_EOF
  1521. if test -f 'lemgroup.c'
  1522. then
  1523.     echo shar: over-writing existing file "'lemgroup.c'"
  1524. fi
  1525. cat << \SHAR_EOF > 'lemgroup.c'
  1526. /*
  1527.  * lemgroup.c - object group maintenance
  1528.  *
  1529.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1530.  */
  1531.  
  1532. #include "lem.h"
  1533.  
  1534. addgroup()
  1535.     {
  1536.     int i, g;
  1537.     g = uniquegroup();
  1538.     forobjects
  1539.     {
  1540.     if (Osel) Ogroup = g;
  1541.     }
  1542.     }
  1543.  
  1544. removegroup()
  1545.     {
  1546.     int i;
  1547.     forobjects
  1548.     {
  1549.     if (Ogroup) Ogroup = 0;
  1550.     }
  1551.     }
  1552.  
  1553. uniquegroup()
  1554.     {
  1555.     int i, groups[256];
  1556.     for(i=0; i<256; i++) groups[i] = 0;
  1557.     for(i=1; i<lastobj; i++) groups[Ogroup]++;
  1558.     for(i=1; i<256; i++)
  1559.     {
  1560.     if (groups[i] == 0) break;
  1561.     }
  1562.     return(groups[i] == 0 ? i : 0);
  1563.     }
  1564. SHAR_EOF
  1565. if test -f 'lemhelp.c'
  1566. then
  1567.     echo shar: over-writing existing file "'lemhelp.c'"
  1568. fi
  1569. cat << \SHAR_EOF > 'lemhelp.c'
  1570. /*
  1571.  * lemhelp.c - give menu of key functions
  1572.  *
  1573.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1574.  */
  1575.  
  1576. #include "lem.h"
  1577. #include "lemfont.h"
  1578.  
  1579. #define HELPCHARS "[IHMABCDEFGLNOPRSTUVWX^?"
  1580.  
  1581. help()
  1582.     {
  1583.     char c;
  1584.     msgpost("[help]: <space> - all; \"/\" - fonts; <key> - function: ");
  1585.     c = getstroke();
  1586.     if (c == ' ') helpall();
  1587.     else if (c == '/') helpfonts();
  1588.     else if (c != '\0') helpkey(c);
  1589.     }
  1590.  
  1591. char *helpmsg(c)
  1592.     char c;
  1593.     {
  1594.     char *s;
  1595.     if (c < ' ') c += ' ';    /* turn ^chars to upper case */
  1596.     switch(UC(c))
  1597.     {
  1598.     case '[': s = "ESC  Delete Mark; Deselect all"; break;
  1599.     case 'A': s = "^A   All select"; break;
  1600.     case 'B': s = "^B   Box-ify selections"; break;
  1601.     case 'C': s = "^C   Copy selections (in place)"; break;
  1602.     case 'D': s = "^D   Delete selections"; break;
  1603.     case 'E': s = "^E   Ellipse-ify selections"; break;
  1604.     case 'F': s = "^F   Force<+key>: 0=reset/1-9=size/Bld/Nrm/Itl/Lft/Rht/Cen";break;
  1605.     case 'G': s = "^G   Group selections"; break;
  1606.     case 'H': s = "BS   Backspace input text"; break;
  1607.     case 'I': s = "TAB  Select marked obj (cyclically)"; break;
  1608.     case 'L': s = "^L   Refresh display"; break;
  1609.     case 'J':
  1610.     case 'M': s = "CR   Add text (if present)"; break;
  1611.     case 'N': s = "^N   No select (deselect all)"; break;
  1612.     case 'O': s = "^O   Output PIC \"filename\""; break;
  1613.     case 'P': s = "^P   Pop (ungroup -- instantiate) selected groups"; break;
  1614.     case 'Q': s = "^Q   Quit"; break;
  1615.     case 'R': s = "^R   Read \"filename\""; break;
  1616.     case 'S': s = "^Sc  Special function escape"; break;
  1617.     case 'T': s = "^Td  Tickmarks (on/off)"; break;
  1618.     case 'U': s = "^U   Undo selections (undelete, untransform)"; break;
  1619.     case 'V': s = "^V   Vector-ify selections"; break;
  1620.     case 'W': s = "^W   Write \"filename\""; break;
  1621.     case 'X': s = "^X   Cut lines (selections scissor normal lines)"; break;
  1622.     case '^': s = "^^   Help"; break;
  1623.     case '?': s = "^^?  Help all"; break;
  1624.     default:  s = "    (undefined)"; break;
  1625.     }
  1626.     return(s);
  1627.     }
  1628.  
  1629. helpkey(c)
  1630.     char c;
  1631.     {
  1632.     msgpost(helpmsg(c));
  1633.     }
  1634.  
  1635. helpall()
  1636.     {
  1637.     int i, x, y;
  1638.     char c;
  1639.     erase();
  1640.     x = 10;
  1641.     y = screenh-fontleading(SYSFONT);
  1642.     for (i=0; i<strlen(HELPCHARS); i++)
  1643.     {
  1644.     int baseline;
  1645.     c = HELPCHARS[i];
  1646.     fontwrite(SYSFONT, x, y, helpmsg(c), EMPHNONE, HELPCOL);
  1647.     baseline = fontleading(SYSFONT);
  1648.     y -= baseline;
  1649.     if (y < baseline) break;
  1650.     }
  1651.     }
  1652.  
  1653. helpfonts()
  1654.     {
  1655.     int i, x, y;
  1656.     char fontmsg[50];
  1657.     erase();
  1658.     x = 10;
  1659.     y = screenh-fontleading(SYSFONT);
  1660.     fontwrite(SYSFONT, x, y, "Current Fonts", EMPHNONE, HELPCOL);
  1661.     y -= 2 * fontleading(SYSFONT);
  1662.     for (i=1; i<rclen; i++)
  1663.     {
  1664.     int baseline;
  1665.     sprintf(fontmsg, "%d    %s%d", i, lemfont[i].dsp, lemfont[i].psize);
  1666.     fontwrite(SYSFONT, x, y, fontmsg, EMPHNONE, HELPCOL);
  1667.     fontwrite(i, x+180, y, "regular", EMPHNONE, HELPCOL);
  1668.     fontwrite(i, x+280, y, "bold",    EMPHBOLD, HELPCOL);
  1669.     fontwrite(i, x+380, y, "italic",  EMPHITAL, HELPCOL);
  1670.     if (gsize == i)
  1671.          {
  1672.          char *S;
  1673.          S = (galign==ALIGNLEFT)?"[L]" : ((gemph==ALIGNRGHT)?"[R]":"[C]");
  1674.          if (gemph == EMPHNONE) fontwrite(i, x+160, y, S,EMPHNONE,HELPCOL);
  1675.          if (gemph == EMPHBOLD) fontwrite(i, x+260, y, S,EMPHBOLD,HELPCOL);
  1676.          if (gemph == EMPHITAL) fontwrite(i, x+360, y, S,EMPHITAL,HELPCOL);
  1677.          }
  1678.     baseline = fontleading(SYSFONT);
  1679.     y -= 2 * baseline;
  1680.     if (y < baseline) break;
  1681.     }
  1682.     }
  1683. SHAR_EOF
  1684. if test -f 'lemik.c'
  1685. then
  1686.     echo shar: over-writing existing file "'lemik.c'"
  1687. fi
  1688. cat << \SHAR_EOF > 'lemik.c'
  1689. /*
  1690.  * lemik.c - ikonas driver for lemming software
  1691.  *
  1692.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1693.  */
  1694.  
  1695. #include "lem.h"
  1696.  
  1697. #include <graphics/ik_const.h>
  1698. #include <local/Locator.h>
  1699. #include <errno.h>
  1700. #include <sys/time.h>
  1701. #include <sgtty.h>
  1702. #include <signal.h>
  1703.  
  1704. #define MASKREG 0
  1705. #define STDIN 0
  1706. #define OBITS 0xffffff
  1707. #define RED   0x0000ff
  1708. #define GREEN 0x00ff00
  1709. #define BLACK 0x000000
  1710. #define WHITE 0xffffff
  1711.  
  1712. struct In_config *Id, *Iopen();
  1713. struct In_state st;
  1714. char *inDevice, *getenv(), readchar();
  1715.  
  1716. /* cursor stuff */
  1717.  
  1718. #define CURLEN 32
  1719. #define CUROFFX 16
  1720. #define CUROFFY 16
  1721. #define LCLK 49
  1722. #define LWYOFF 33
  1723.  
  1724. #define SETCUR(x, y) cur[(y)] |= 1<<((x));
  1725. #define HL(a,b) (((a)<<16)+((b)&0xffff))
  1726.  
  1727. static int cur[CURLEN];
  1728.  
  1729. /*
  1730.  * external routines
  1731.  */
  1732.  
  1733. setpixelrunh(x, y, wid, val)
  1734.     {
  1735.     int i;
  1736.     for (i=0; i<wid; i++)
  1737.     Ik_diowr(IK_XY_ADDR, x+i, 511-y, val);
  1738.     }
  1739.  
  1740. setpixelrunv(x, y, wid, val)
  1741.     {
  1742.     int i;
  1743.     for (i=0; i<wid; i++)
  1744.     Ik_diowr(IK_XY_ADDR, x, 511-y+i, val);
  1745.     }
  1746.  
  1747. start()
  1748.     {
  1749. /*
  1750.  * system defaults
  1751.  */
  1752.     screenw = 512;
  1753.     screenh = 512;
  1754.     cred = RED;
  1755.     cgreen = GREEN;
  1756.     cblack = BLACK;
  1757.     cwhite = WHITE;
  1758.     tickdot = 1;
  1759. /*
  1760.  * initialization
  1761.  */
  1762.     startcbreak();
  1763.     Ik_open();
  1764.     Ik_init();
  1765. /* Ik_zoom_pan(0, 0, 508, 480, 0, 0, 1, 1, 0, 1); */ /* last for 1:1,not 4:3 */
  1766.     Ik_mask_set(MASKREG, OBITS);
  1767.     cursorenable();
  1768.  
  1769.     if( (inDevice = getenv("INPUT") ) == NULL )
  1770.     inDevice = "ikonas";
  1771.     if ( (Id = Iopen(inDevice, I_DEFAULT)) == NULL) err("can't open tablet");
  1772.     Iwindow( Id, 0, 511, 0, 511, 0, 32 );
  1773.     Ictl(Id, I_ENABLE, 0);    /* make the tablet free-running *sigh* */
  1774.     }
  1775.  
  1776. stop()
  1777.     {
  1778.     cursordisable();
  1779.     Iclose(Id);
  1780.     Ik_close();
  1781.     stopcbreak();
  1782.     }
  1783.  
  1784. getevent(xdown, ydown, xup, yup, ch)
  1785.     char *ch;
  1786.     int *xdown, *ydown, *xup, *yup;
  1787.     {
  1788.     int lastx, lasty, mousedesc, dev;
  1789.     mousedesc = fileno(Id->In_ifp);
  1790.     dev = checkevent(mousedesc, STDIN, 1);    /*  blocking (hah!) */
  1791.     if (dev == STDIN)
  1792.     {
  1793.     *ch = readchar();
  1794.     return(((*ch < ' ') || (*ch == '\177')) ? CNTRL : ALPHA);
  1795.     }
  1796.     if (dev == mousedesc)
  1797.     {
  1798.     Iread(Id, &st, COORDINATES);
  1799.     cursorplace(st.x, st.y);
  1800.     lastx = st.x;
  1801.     lasty = st.y;
  1802.     if (st.button == 0) return(NOEVT);
  1803.     else
  1804.         {
  1805.         *xdown = st.x;
  1806.         *ydown = st.y;
  1807.         do  {
  1808.         Iread(Id, &st, COORDINATES);
  1809.         *yup = st.y;
  1810.         *xup = st.x;
  1811.         if ((lastx != st.x) || (lasty != st.y)) cursorplace(st.x, st.y);
  1812.         lastx = st.x;
  1813.         lasty = st.y;
  1814.         } while (st.button != 0);
  1815.         }
  1816.     return(MOUSE);
  1817.     }
  1818.     return(NOEVT);
  1819.     }
  1820.  
  1821. charshow(str)
  1822.     char *str;
  1823.     {
  1824.     fprintf(stdout, "%s", str);
  1825.     fflush(stdout);
  1826.     }
  1827.  
  1828. charunshow(n)
  1829.     {
  1830.     int i;
  1831.     for (i=0; i<n; i++) fprintf(stdout, "%c %c", '\b', '\b');
  1832.     fflush(stdout);
  1833.     }
  1834.  
  1835. drawvec(x0, y0, x1, y1, col, wid, emph)
  1836.     {
  1837.     drawline(x0, y0, x1, y1, wid, col, emph);
  1838.     }
  1839.  
  1840. erase()
  1841.     {
  1842.     Ik_clear();
  1843.     }
  1844.  
  1845. /*
  1846.  * internal routines
  1847.  */
  1848.  
  1849. cursorenable()
  1850.     {
  1851.     long i;
  1852.     int ncolor[IK_MAP_SIZE];
  1853.     Ik_set_mode( SET_DURING_RETRACE );
  1854.     Ik_mask_set(0, 0xffffff);
  1855.     Ik_dmard(IK_WD_ADDR, IK_COLOUR_MAPS, IK_MAP_SIZE*0, ncolor, IK_MAP_SIZE);
  1856.     for (i=0; i<IK_MAP_SIZE; i++) ncolor[i] = (-1) ^ ncolor[i];
  1857.     Ik_dmawr(IK_WD_ADDR, IK_COLOUR_MAPS, IK_MAP_SIZE*1, ncolor, IK_MAP_SIZE);
  1858.     Ik_dmawr(IK_WD_ADDR, IK_COLOUR_MAPS, IK_MAP_SIZE*3, ncolor, IK_MAP_SIZE);
  1859.     Ik_diowr( IK_WD_ADDR, IK_XBAR_SWITCH, 32, 32); /* guarantee incursor bit */
  1860.     for (i=0; i<CURLEN; i++) cur[i] = 0;    /* clear cursor */
  1861.     for (i=0; i<CURLEN/4; i++)            /* draw open + sign */
  1862.     {
  1863.     SETCUR(i+CURLEN/8,   CURLEN/2);
  1864.     SETCUR(7*CURLEN/8-i, CURLEN/2);
  1865.     SETCUR(CURLEN/2,     i+CURLEN/8);
  1866.     SETCUR(CURLEN/2,     7*CURLEN/8-i);
  1867.     }
  1868.     Ik_curs_map(cur, CURLEN/2, CURLEN/2);
  1869.     cursorplace(0, 0);
  1870.     }
  1871.  
  1872. cursordisable()
  1873.     {
  1874.     int i;
  1875.     for (i=0; i<CURLEN; i++) cur[i] = 0;
  1876.     Ik_curs_map(cur, 0, 0);
  1877.     Ik_diowr( IK_WD_ADDR, IK_FBC_REGS, FBC_MODE, HL(LCLK,  0x40));
  1878.     }
  1879.  
  1880. cursorplace(x, y)
  1881.     {
  1882.     Ik_diowr(IK_WD_ADDR, IK_FBC_REGS, FBC_CURSOR,
  1883.     HL((511-y)+LWYOFF-CUROFFY-5, x-CUROFFX));
  1884.     Ik_diowr( IK_WD_ADDR, IK_FBC_REGS, FBC_MODE, HL(LCLK,  0x44));
  1885.     }
  1886.  
  1887. /*
  1888.  * UNIX code to test for pending STDIN characters (in CBREAK mode)
  1889.  * and capture ^Z interruptions for the sake of CBREAK problems.
  1890.  */
  1891.  
  1892. int stopcatch();
  1893.  
  1894. stopcbreak()
  1895.     {
  1896.     struct sgttyb tty;
  1897.     ioctl(STDIN, TIOCGETP, &tty);
  1898.     tty.sg_flags &= ~CBREAK;
  1899.     tty.sg_flags |= ECHO;
  1900.     ioctl(STDIN, TIOCSETP, &tty);
  1901.     signal(SIGTSTP, SIG_DFL);
  1902.     }
  1903.  
  1904. startcbreak()
  1905.     {
  1906.     struct sgttyb tty;
  1907.     ioctl(STDIN, TIOCGETP, &tty);
  1908.     tty.sg_flags |= CBREAK;
  1909.     tty.sg_flags &= ~ECHO;
  1910.     ioctl(STDIN, TIOCSETP, &tty);
  1911.     signal(SIGTSTP, stopcatch);
  1912.     }
  1913.  
  1914. stopcatch()
  1915.     {
  1916. /* ^Z just typed.  */
  1917.     stopcbreak();
  1918.     sigsetmask (sigblock(0) & ~(1<<(SIGTSTP-1))); /* turn SIGTSTP on */
  1919.     kill(0, SIGTSTP);            /* STOP THYSELF! */
  1920. /* you just returned */
  1921.     startcbreak();            /* restore action for next time */
  1922.     }
  1923.  
  1924. checkevent(l, r, blockflag)
  1925.     {
  1926.     extern int errno;
  1927.     int rdesc, retcode, bits;
  1928.     struct timeval tv;
  1929.     do    {
  1930.     rdesc = (1<<l) | (1<<r);
  1931.     bits = (l > r) ? l+1 : r+1;
  1932.     bzero(&tv, sizeof tv);        /* zero timer -> poll, no waiting */
  1933.     retcode = select(bits, &rdesc, 0, 0, blockflag ? 0 : &tv);
  1934.     } while ((retcode < 0) && (errno == EINTR));
  1935.     if (retcode <= 0) return(-1);
  1936.     return((rdesc == (1<<l)) ? l : r);
  1937.     }
  1938.  
  1939. char readchar()
  1940.     {
  1941.     char ch;
  1942.     read(STDIN, &ch, 1);
  1943.     return(ch);
  1944.     }
  1945.  
  1946. writescan(x, y, pixels, outaddr, color)
  1947.     int x, y, pixels, *outaddr, color;
  1948.     {
  1949.     static int IKbuf[512];
  1950.     int words, *bufbase;
  1951.  
  1952. /* register */
  1953.     register int next, *wordbase, regfontcolor;
  1954.  
  1955.     if (pixels <= 0) return;        /* PARANOIA: should not ever happen */
  1956.  
  1957.     regfontcolor = color;        /* for a little speed */
  1958.     words = (pixels - 1) / 32 + 1;
  1959.     bufbase = IKbuf;
  1960.     Ik_dmard(IK_XY_ADDR, x, y, IKbuf, pixels);
  1961.  
  1962.     ++words;
  1963.     while (--words)
  1964.     {
  1965.     next = *outaddr;
  1966.     ++outaddr;
  1967.     wordbase = bufbase;
  1968.     while (next)
  1969.         {
  1970.         if (next < 0) *wordbase = regfontcolor;
  1971.         ++wordbase;
  1972.         next<<=1;
  1973.         }
  1974.     bufbase += 32;
  1975.     }
  1976.     Ik_dmawr(IK_XY_ADDR, x, y, IKbuf, pixels);
  1977.     }
  1978. SHAR_EOF
  1979. if test -f 'lemio.c'
  1980. then
  1981.     echo shar: over-writing existing file "'lemio.c'"
  1982. fi
  1983. cat << \SHAR_EOF > 'lemio.c'
  1984. /*
  1985.  * lemio.c - I/O routines
  1986.  *
  1987.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  1988.  */
  1989.  
  1990. #include "lem.h"
  1991.  
  1992. writefile()
  1993.     {
  1994.     int i;
  1995.     char *fname;
  1996.     FILE *f;
  1997.     if (lastobj == 1) return;    /* nothing on display -- fast return */
  1998.     fname = prompt("output file: ");
  1999.     f = (fname && (strlen(fname) > 1)) ? fopen(fname, "w") : 0;
  2000.     if (f)
  2001.     {
  2002.     fprintf(f, "LEMMING %d\n", VERNO);
  2003.     forobjects
  2004.         {
  2005.         if (Onotdel)
  2006.         {
  2007.         fprintf(f, "%c %d %d %d %d %d %c %c",
  2008.           Otype, Oxs, Oys, Oxe, Oye, Osize, Oalign, Oemph);
  2009.         if (Otext && strlen(Otext)) fprintf(f, " \\%s", Otext);
  2010.         fprintf(f, "\n");
  2011.         }
  2012.         }
  2013.     fclose(f);
  2014.     changes = 0;
  2015.     msgpost("output done");
  2016.     }
  2017.     else msgpost("output failed");
  2018.     free(fname);
  2019.     }
  2020.  
  2021. readfileint(fname)
  2022.     char *fname;
  2023.     {
  2024.     int i, g, ver;
  2025.     char *s, fline[MAXCHAR+50];
  2026.     FILE *f;
  2027.     f = 0;
  2028.     if (fname && (strlen(fname) > 0))
  2029.     {
  2030.     f = fopen(fname, "r");
  2031.     if (!f)
  2032.         {
  2033.         char filename[100];
  2034.         sprintf(filename, "%s.%s", fname, LEMEXTN);
  2035.         f = fopen(filename, "r");
  2036.         }
  2037.     }
  2038.     if (f)
  2039.     {
  2040.     fgets(fline, sizeof(fline), f);
  2041.     if ((sscanf(fline, "LEMMING %d", &ver) == 1) && (ver == VERNO))
  2042.         {
  2043.         g = uniquegroup();
  2044.         while (1)
  2045.         {
  2046.         int x0, y0, x1, y1, size;
  2047.         fgets(fline, sizeof(fline), f);
  2048.         if (feof(f)) break;
  2049.         i = objalloc(0);
  2050.         sscanf(fline, "%c %d %d %d %d %d %c %c", &Otype, &x0, &y0,
  2051.             &x1, &y1, &size, &Oalign, &Oemph);
  2052.         Oxs = x0;
  2053.         Oys = y0;
  2054.         Oxe = x1;
  2055.         Oye = y1;
  2056.         Osize = size;
  2057. /*
  2058.  * possible input text
  2059.  */
  2060.         s = fline;
  2061.         while ((*s) && (*s != '\\')) s++;
  2062.         if (*s == '\\') s++;
  2063.         if (*s) s[strlen(s)-1] = '\0';    /* snuff trailing CR */
  2064.         Otext = (s && strlen(s)) ? salloc(s) : 0;
  2065. /*
  2066.  * now assign attributes
  2067.  */
  2068.         Ogroup = g;
  2069.         Ostat = DEL;
  2070.         objresize(i);
  2071.         objectop(i, DEL, SEL);
  2072.         }
  2073.         fclose(f);
  2074.         msgpost("input done");
  2075.         }
  2076.     else msgpost("bogus input file");
  2077.     }
  2078.     else msgpost("input not found");
  2079.     }
  2080.  
  2081. readfile()
  2082.     {
  2083.     char *fname;
  2084.     fname = prompt("input file: ");
  2085.     readfileint(fname);
  2086.     free(fname);
  2087.     }
  2088. SHAR_EOF
  2089. if test -f 'lemline.c'
  2090. then
  2091.     echo shar: over-writing existing file "'lemline.c'"
  2092. fi
  2093. cat << \SHAR_EOF > 'lemline.c'
  2094. /*
  2095.  * lemline.c - line primities
  2096.  *
  2097.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  2098.  */
  2099.  
  2100. #include "lem.h"
  2101.  
  2102. lineadd(x0, y0, x1, y1)
  2103.     {
  2104.     int i;
  2105.     if ((x0 == x1) && (y0 == y1)) return;
  2106.     i = objalloc(LINE);
  2107.     lineupdate(i, x0, y0, x1, y1);
  2108.     objnew(i);
  2109.     }
  2110.  
  2111. lineresize(i)
  2112.     {
  2113.     }
  2114.     
  2115. lineupdate(i, x0, y0, x1, y1)
  2116.     {
  2117.     Oxs = x0;
  2118.     Oys = y0;
  2119.     Oxe = x1;
  2120.     Oye = y1;
  2121.     }
  2122.  
  2123. linenearpt(i, x, y)
  2124.     {
  2125.     int tol, hy;
  2126.     if (ptinrect(x, y, Oxl, Oyl, Oxh, Oyh, LINETOL) == 0) return(0);
  2127.     hy = hypot(Ow, Oh);
  2128.     if (hy < SHRTTOL) return(1);
  2129.     tol = ABS(((x-Ox)*Oh - (y-Oy)*Ow)) / hy;
  2130.     return(LINETOL > tol);
  2131.     }
  2132.  
  2133. lineinrect(i, xl, yl, xh, yh)
  2134.     {
  2135.     return(ptinrect(Oxl, Oyl, xl, yl, xh, yh, LINETOL) &&
  2136.     ptinrect(Oxh, Oyh, xl, yl, xh, yh, LINETOL));
  2137.     }
  2138.  
  2139. linecantug(i, x, y)
  2140.     {
  2141.     return(linenearpt(i, x, y));
  2142.     }
  2143.     
  2144. linetug(i, xs, ys, xe, ye)
  2145.     {
  2146.     if (dist(Oxs, Oys, xs, ys) < TUGPROX) lineupdate(i, xe, ye, Oxe, Oye);
  2147.     else if (dist(Oxe, Oye, xs, ys) < TUGPROX) lineupdate(i, Oxs, Oys, xe, ye);
  2148.     else linemove(i, xe-xs, ye-ys);
  2149.     }
  2150.  
  2151. linealign(i, x, y)
  2152.     int *x, *y;
  2153.     {
  2154.     if (dist(Oxs, Oys, *x, *y) < ENDTOL)
  2155.     {
  2156.     *x = Oxs;
  2157.     *y = Oys;
  2158.     }
  2159.     else if (dist(Oxe, Oye, *x, *y) < ENDTOL)
  2160.     {
  2161.     *x = Oxe;
  2162.     *y = Oye;
  2163.     }
  2164.     else
  2165.     {
  2166.     int frac;
  2167.     frac = (ABS(Ow) > ABS(Oh)) ? (12*(*x-Oxs)+6)/Ow : (12*(*y-Oys)+6)/Oh;
  2168.     *x = ((12-frac)*Oxs + frac*Oxe)/12;
  2169.     *y = ((12-frac)*Oys + frac*Oye)/12;
  2170.     }
  2171.     }
  2172.  
  2173. linemove(i, x, y)
  2174.     {
  2175.     objsupmove(i, x, y);
  2176.     }
  2177.  
  2178. lineaffine(i, m11, m12, m21, m22)
  2179.     float m11, m12, m21, m22;
  2180.     {
  2181.     objsupaffine(i, m11, m12, m21, m22, 1);
  2182.     }
  2183.     
  2184. linedraw(i, col)
  2185.     {
  2186.     int wid;
  2187.     wid = lemfont[Osizer].thick;
  2188.     drawvec(Oxs, Oys, Oxe, Oye, col, wid, Oemph);
  2189.     if (Oalign == ALIGNLEFT)
  2190.     {
  2191.     int h, x, y, x1, y1;
  2192.     h = hypot(Ow, Oh)*13;
  2193.     x = Ow*ARROWLEN;
  2194.     y = Oh*ARROWLEN;
  2195.     x1 = ( x*12-y*5)/h;
  2196.     y1 = ( x*5+y*12)/h;
  2197.     drawvec(Oxs, Oys, Oxs+x1, Oys+y1, col, wid, EMPHNONE);
  2198.     x1 = ( x*12+y*5)/h;
  2199.     y1 = (-x*5+y*12)/h;
  2200.     drawvec(Oxs, Oys, Oxs+x1, Oys+y1, col, wid, EMPHNONE);
  2201.     }
  2202.     if (Oalign == ALIGNRGHT)
  2203.     {
  2204.     int h, x, y, x1, y1;
  2205.     h = hypot(Ow, Oh)*13;
  2206.     x = Ow*ARROWLEN;
  2207.     y = Oh*ARROWLEN;
  2208.     x1 = ( x*12-y*5)/h;
  2209.     y1 = ( x*5+y*12)/h;
  2210.     drawvec(Oxe, Oye, Oxe-x1, Oye-y1, col, wid, EMPHNONE);
  2211.     x1 = ( x*12+y*5)/h;
  2212.     y1 = (-x*5+y*12)/h;
  2213.     drawvec(Oxe, Oye, Oxe-x1, Oye-y1, col, wid, EMPHNONE);
  2214.     }
  2215.     }
  2216. SHAR_EOF
  2217. #    End of shell archive
  2218. exit 0
  2219.  
  2220.  
  2221. -- 
  2222.  
  2223. Rich $alz            "Anger is an energy"
  2224. Cronus Project, BBN Labs    rsalz@bbn.com
  2225. Moderator, comp.sources.unix    sources@uunet.uu.net
  2226.